package pruebas;
import junit.framework.TestCase;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import juego.AvionCivil;
import juego.Avioneta;
import juego.Bombardero;
import juego.Botin;
import juego.Caza;
import juego.Cohete;
import juego.Energia;
import juego.Explorador;
import juego.Impacto;
import juego.Coordenada;
import juego.Laser;
import juego.Movil;
import juego.Torpedo;

public class TestAvioneta extends TestCase {
	
	public void testProvocarHuida(){
		ArrayList<Movil> listaDeObjetos = new ArrayList<Movil>();
		ArrayList<Botin> listaDeBotines = new ArrayList<Botin>();
		
		Coordenada coordNave = new Coordenada(0,0);
		Avioneta unaNave = new Avioneta(coordNave);
		unaNave.designarGuia();
		
		Coordenada coordLaser = new Coordenada(10,15);
		Laser unLaser = new Laser(coordLaser);
		
		Coordenada coordCohete = new Coordenada(8,15);
		Cohete unCohete = new Cohete(coordCohete);
		
		unLaser.hacerLeal();
		
		unCohete.hacerLeal();
		
		Coordenada coordEnemigo1 = new Coordenada(50,50);
		Explorador enemigo1 = new Explorador(coordEnemigo1);
		
		Coordenada coordEnemigo2 = new Coordenada(40,50);
		Caza enemigo2 = new Caza(coordEnemigo2);
		
		Coordenada coordEnemigo3 = new Coordenada(30,50);
		Avioneta enemigo3 = new Avioneta(coordEnemigo3);
		
		Coordenada coordEnemigo4 = new Coordenada(20,50);
		Bombardero enemigo4 = new Bombardero(coordEnemigo4);
	
		AvionCivil amigo1 = new AvionCivil(-100,-100);
		
		Coordenada coordAmigo2 = new Coordenada(100,100);
		Laser amigo2 = new Laser(coordAmigo2);
		amigo2.hacerLeal();
		
		Coordenada coordEnemigo5 = new Coordenada(10,50);
		Laser enemigo5 = new Laser(coordEnemigo5);
		
		listaDeObjetos.add(amigo1);
		listaDeObjetos.add(enemigo1);
		listaDeObjetos.add(enemigo3);
		listaDeObjetos.add(unLaser);
		listaDeObjetos.add(unaNave);
		listaDeObjetos.add(enemigo4);
		listaDeObjetos.add(enemigo5);
		listaDeObjetos.add(amigo2);
		listaDeObjetos.add(enemigo2);
		listaDeObjetos.add(unCohete);
			
		//Destruccion
		unaNave.vivir(listaDeObjetos,listaDeBotines);
		assertFalse(listaDeObjetos.contains(unaNave)); 
		assertFalse(listaDeObjetos.contains(unLaser)); 
		assertFalse(listaDeObjetos.contains(unCohete)); 

		//Huida
		//Siguen igual
		amigo1.vivir(listaDeObjetos,listaDeBotines);
		Coordenada coord1 = amigo1.verUbicacion();
		int x1 = coord1.obtenerCoordenadaX();
		int y1 = coord1.obtenerCoordenadaY();
		assertTrue(x1 == (-100));
		assertTrue(y1 == (-95));
		
		amigo2.vivir(listaDeObjetos,listaDeBotines);
		Coordenada coord2 = amigo2.verUbicacion();
		int x2 = coord2.obtenerCoordenadaX();
		int y2 = coord2.obtenerCoordenadaY();
		assertTrue(x2 == (100));
		assertTrue(y2 == (90));
		
		enemigo5.vivir(listaDeObjetos,listaDeBotines);
		Coordenada coord3 = enemigo5.verUbicacion();
		int x3 = coord3.obtenerCoordenadaX();
		int y3 = coord3.obtenerCoordenadaY();
		assertTrue(x3 == (10));
		assertTrue(y3 == (60));
		
		//Huyen
		enemigo1.vivir(listaDeObjetos,listaDeBotines);
		Coordenada coord4 = enemigo1.verUbicacion();
		int x4 = coord4.obtenerCoordenadaX();
		int y4 = coord4.obtenerCoordenadaY();
		assertTrue(x4 == (50));
		assertTrue(y4 == (40));
		
		enemigo2.vivir(listaDeObjetos,listaDeBotines);
		Coordenada coord5 = enemigo2.verUbicacion();
		int x5 = coord5.obtenerCoordenadaX();
		int y5 = coord5.obtenerCoordenadaY();
		assertTrue(x5 == (40));
		assertTrue(y5 == (47));
		
		enemigo3.vivir(listaDeObjetos,listaDeBotines);
		Coordenada coord6 = enemigo3.verUbicacion();
		int x6 = coord6.obtenerCoordenadaX();
		int y6 = coord6.obtenerCoordenadaY();
		assertTrue(x6 == (30));
		assertTrue(y6 == (35));
		
		enemigo4.vivir(listaDeObjetos,listaDeBotines);
		Coordenada coord7 = enemigo4.verUbicacion();
		int x7 = coord7.obtenerCoordenadaX();
		int y7 = coord7.obtenerCoordenadaY();
		assertTrue(x7 == (20));
		assertTrue(y7 == (45));
		
	}
	
	public void testColision(){
		ArrayList<Movil> listaDeObjetos = new ArrayList<Movil>();
		ArrayList<Botin> listaDeBotines = new ArrayList<Botin>();
		
		Avioneta exp = new Avioneta(0,0);
		
		Coordenada coordH2 = new Coordenada(10,15);
		Laser h2 = new Laser(coordH2);
		
		Coordenada coordH3 = new Coordenada(0,33);
		Laser h3 = new Laser(coordH3);
		
		h2.hacerLeal();
		h3.hacerLeal();
		
		listaDeObjetos.add(exp);
		listaDeObjetos.add(h2);
		listaDeObjetos.add(h3);
		
		int puntaje = (exp.vivir(listaDeObjetos,listaDeBotines));
		assertTrue(listaDeObjetos.contains(exp));
		assertFalse(listaDeObjetos.contains(h2));
		assertTrue(puntaje == 0);
		
		int puntaje2 = (exp.vivir(listaDeObjetos,listaDeBotines));
		assertFalse(listaDeObjetos.contains(exp));
		assertFalse(listaDeObjetos.contains(h3));
		assertTrue(puntaje2 == 20);
	}
	
	public void testColisionFuerzaAmigo(){
		ArrayList<Movil> listaDeObjetos = new ArrayList<Movil>();
		ArrayList<Botin> listaDeBotines = new ArrayList<Botin>();
		
		Coordenada coordExp = new Coordenada(0,0);
		Avioneta exp = new Avioneta(coordExp);
		
		Coordenada coordH2 = new Coordenada(15,0);
		Laser h2 = new Laser(coordH2);
		
		Coordenada coordH3 = new Coordenada(32,0);
		Laser h3 = new Laser(coordH3);
		
		listaDeObjetos.add(exp);
		listaDeObjetos.add(h2);
		listaDeObjetos.add(h3);
		
		int puntaje = (exp.vivir(listaDeObjetos,listaDeBotines));
		assertTrue(listaDeObjetos.contains(exp));
		assertTrue(listaDeObjetos.contains(h2));
		assertTrue(puntaje == 0);
		
		int puntaje2 = (exp.vivir(listaDeObjetos,listaDeBotines));
		assertTrue(listaDeObjetos.contains(exp));
		assertTrue(listaDeObjetos.contains(h3));
		assertTrue(puntaje2 == 0);
	}

	public void testDisparar() {
		ArrayList<Movil> listaDeObjetos = new ArrayList<Movil>();
		ArrayList<Botin> listaDeBotines = new ArrayList<Botin>();
		Coordenada coordExp = new Coordenada(0,0);
		Avioneta exp = new Avioneta(coordExp);
		listaDeObjetos.add(exp);
		exp.vivir(listaDeObjetos,listaDeBotines);
		Movil unElemento = listaDeObjetos.get(1);
		Coordenada coord = unElemento.verUbicacion();
		int x = coord.obtenerCoordenadaX();
		int y = coord.obtenerCoordenadaY();
		assertTrue(x == (0));
		assertTrue(y == (15));
		assertEquals(listaDeObjetos.size(),2);
	}
	
	public void testDispararMuerto() {
		ArrayList<Movil> listaDeObjetos = new ArrayList<Movil>();
		ArrayList<Botin> listaDeBotines = new ArrayList<Botin>();
		Coordenada coordExp = new Coordenada(0,0);
		Avioneta exp = new Avioneta(coordExp);
		listaDeObjetos.add(exp);
		Coordenada coordP1 = new Coordenada(10,15);
		Torpedo p1 = new Torpedo(coordP1);
		p1.hacerLeal();
		listaDeObjetos.add(p1);
		exp.vivir(listaDeObjetos,listaDeBotines);	
		assertTrue((listaDeObjetos.size()) == 0);	
	}
	
	public void testImpactoProvocado(){
		
		Movil movil = new Avioneta(0,8);
		Energia energia = new Energia(30);
		Impacto impacto = movil.impactoProvocado();
		impacto.herir(energia);
		assertEquals(20, energia.verEnergia());
		
	};

	public void testMovimiento(){
		ArrayList<Movil> listaDeObjetos = new ArrayList<Movil>();
		ArrayList<Botin> listaDeBotines = new ArrayList<Botin>();
		
		Coordenada coordH1 = new Coordenada(0,0);
		Avioneta h1 = new Avioneta(coordH1);
		listaDeObjetos.add(h1);
		
		h1.vivir(listaDeObjetos,listaDeBotines);
		Coordenada coord1 = h1.verUbicacion();
		int x1 = coord1.obtenerCoordenadaX();
		int y1 = coord1.obtenerCoordenadaY();
		assertTrue(x1 == (0));
		assertTrue(y1 == (15));
		
		for (int i=1;i<10;i++){
			h1.vivir(listaDeObjetos,listaDeBotines);}
		Coordenada coord2 = h1.verUbicacion();
		int x2 = coord2.obtenerCoordenadaX();
		int y2 = coord2.obtenerCoordenadaY();
		assertTrue(x2 == (0));
		assertTrue(y2 == (150));
		
		for (int i=1;i<11;i++){
			h1.vivir(listaDeObjetos,listaDeBotines);}
		Coordenada coord3 = h1.verUbicacion();
		int x3 = coord3.obtenerCoordenadaX();
		int y3 = coord3.obtenerCoordenadaY();
		assertTrue(x3 == (0));
		assertTrue(y3 == (0));
		
		for (int i=1;i<11;i++){
			h1.vivir(listaDeObjetos,listaDeBotines);}
		Coordenada coord4 = h1.verUbicacion();
		int x4 = coord4.obtenerCoordenadaX();
		int y4 = coord4.obtenerCoordenadaY();
		assertTrue(x4 == (0));
		assertTrue(y4 == (150));
		
		for (int i=1;i<11;i++){
			h1.vivir(listaDeObjetos,listaDeBotines);}
		Coordenada coord5 = h1.verUbicacion();
		int x5 = coord5.obtenerCoordenadaX();
		int y5 = coord5.obtenerCoordenadaY();
		assertTrue(x5 == (0));
		assertTrue(y5 == (0));
		
	}
	
	public void testFueraDelEscenario(){
		ArrayList<Movil> listaDeMoviles = new ArrayList<Movil>();
		ArrayList<Botin> listaDeBotines = new ArrayList<Botin>();
		
		Avioneta avion = new Avioneta(404,460);
		listaDeMoviles.add(avion);
		
		assertTrue((listaDeMoviles.size() == 1));
		assertTrue(avion.estaVivo());
		
		for (int i = 1; i < 4; i++){
			avion.vivir(listaDeMoviles,listaDeBotines);
		}
		
		assertTrue((listaDeMoviles.size() == 0));
		assertFalse(avion.estaVivo());
	}
	
	


	private static void persistir(String archivo, Avioneta nave) {
		try {

			Document doc = DocumentBuilderFactory.newInstance()
					.newDocumentBuilder().newDocument();

			Element element = nave.getElement(doc);
			doc.appendChild(element);

			Transformer transformer = TransformerFactory.newInstance()
					.newTransformer();
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			transformer.transform(new DOMSource(doc), new StreamResult(
					new PrintStream(archivo)));

		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerFactoryConfigurationError e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		}
	}

	private static Avioneta recuperar(String archivo) {
		try {
		
			Document doc = DocumentBuilderFactory.newInstance()
					.newDocumentBuilder().parse(new File(archivo));
			Element element = doc.getDocumentElement();

			Avioneta nave = Avioneta.fromElement(element);
			return nave;
		
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
	
		return null;
	}



	public void testPersistencia() {

		String archivo = "avioneta_java.xml";
		Avioneta naveOriginal = new Avioneta(5,40);
		assertTrue(naveOriginal.estaVivo());
		persistir(archivo, naveOriginal);
		Avioneta naveRecuperada = recuperar(archivo);
		assertEquals(5,naveRecuperada.getX());
		assertEquals(40,naveRecuperada.getY());
		assertFalse(naveRecuperada.verLealtad());
		assertTrue(naveRecuperada.estaVivo());
		ArrayList<Movil> lista = new ArrayList<Movil>();
		
		naveOriginal.vivir(new ArrayList<Movil>(),new ArrayList<Botin>());
		naveRecuperada.vivir(lista,new ArrayList<Botin>());
		assertEquals(naveOriginal.getX(),naveRecuperada.getX());
		assertEquals(naveOriginal.getY(),naveRecuperada.getY());
		assertEquals(1,lista.size());
//		Movil proyectil = lista.get(0);
//		System.out.println(proyectil.getClass());
		
		
		
		
		
	}
	
	
	
}
	
